/*
 * UlfBagging.java
 *
 * Created on den 20 oktober 2008, 17:18
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package weka.classifiers.meta;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Vector;

import weka.core.Instance;
import weka.core.Instances;
import weka.core.Option;
import weka.core.Utils;
/**
 *
 * @author tul
 */
public class UlfBagging extends Bagging {
    protected String m_filename = "UlfBagging.txt";
    
    /** Creates a new instance of UlfBagging */
    public UlfBagging () {
        super ();
        
        try{
            PrintWriter w;
            w = new PrintWriter (new BufferedWriter (new FileWriter (m_filename, false)));
            w.close ();
        } catch (Exception e) {
        }
    }
    public void buildClassifier (Instances data) throws Exception {
        super.buildClassifier (data);
        
        PrintWriter w;
        w = new PrintWriter (new BufferedWriter (new FileWriter (m_filename, true)));
        w.println (Integer.toString (data.numInstances ()));
        for (Enumeration<Instance> enu = data.enumerateInstances (); enu.hasMoreElements ();){
            Instance instance = enu.nextElement ();
            this.distributionForInstance (instance);
            
            /*double[] tmp = instance.toDoubleArray ();
            for (int i = 0; i < tmp.length; i++)
                w.print (Double.toString (tmp[i]) + " ");
            w.print ("- " + this.classifyInstance (instance));
            double [] sums = new double [instance.numClasses ()];
            if (instance.classAttribute ().isNumeric () != true) {
                w.print (":");
                sums = this.distributionForInstance (instance);
                for (int j = 0; j < instance.numClasses (); j++)
                    w.print (' ' + Double.toString (sums[j]));
            }
            w.print ("- ");
            for (int i = 0; i < m_NumIterations; i++) {
                w.print (Double.toString (m_Classifiers[i].classifyInstance (instance)));
                if (instance.classAttribute ().isNumeric () != true) {
                    w.print (":");
                    sums = m_Classifiers[i].distributionForInstance (instance);
                    for (int j = 0; j < instance.numClasses (); j++)
                        w.print (' ' + Double.toString (sums[j]));
                }
                w.print ("; ");
            }
            w.println ();
             */
        }
        w.println ();
        w.close ();
    }
    
    /**
     * Calculates the class membership probabilities for the given test
     * instance.
     *
     * @param instance the instance to be classified
     * @return preedicted class probability distribution
     * @exception Exception if distribution can't be computed successfully
     */
    public double[] distributionForInstance (Instance instance) throws Exception {
        PrintWriter w;
        w = new PrintWriter (new BufferedWriter (new FileWriter (m_filename, true)));
        
        double[] tmp = instance.toDoubleArray ();
        for (int i = 0; i < tmp.length; i++)
            w.print (Double.toString (tmp[i]) + " ");
        w.print ("- ");
        double [] sums = new double [instance.numClasses ()];
        for (int i = 0; i < m_NumIterations; i++) {
            w.print (Double.toString (m_Classifiers[i].classifyInstance (instance)));
            if (instance.classAttribute ().isNumeric () != true) {
                w.print (":");
                sums = m_Classifiers[i].distributionForInstance (instance);
                for (int j = 0; j < instance.numClasses (); j++)
                    w.print (' ' + Double.toString (sums[j]));
            }
            w.print ("; ");
        }
        w.println ();
        w.close ();
        return super.distributionForInstance (instance);
    }
    
    public Enumeration listOptions () {
        
        Vector newVector = new Vector (1);
        
        newVector.addElement (new Option (
                "\tName of file. (default 'UlfBagging.txt')",
                "FN", 1, "-FN"));
        
        Enumeration enu = super.listOptions ();
        while (enu.hasMoreElements ()) {
            newVector.addElement (enu.nextElement ());
        }
        return newVector.elements ();
    }
    
    public void setOptions (String[] options) throws Exception {
        
        setFilename (Utils.getOption ("FN", options));
        
        super.setOptions (options);
    }
    
    /**
     * Gets the current settings of the Classifier.
     *
     * @return an array of strings suitable for passing to setOptions
     */
    public String [] getOptions () {
        
        
        String [] superOptions = super.getOptions ();
        String [] options = new String [superOptions.length + 2];
        
        int current = 0;
        options[current++] = "-FN";
        options[current++] = "" + getFilename ();
        
        System.arraycopy (superOptions, 0, options, current,
                superOptions.length);
        
        current += superOptions.length;
        while (current < options.length) {
            options[current++] = "";
        }
        return options;
    }
    
    /**
     * Returns the tip text for this property
     * @return tip text for this property suitable for
     * displaying in the explorer/experimenter gui
     */
    public String filenameTipText () {
        return "Name of outputfile for bagging models.";
    }
    
    /**
     * Gets the size of each bag, as a percentage of the training set size.
     *
     * @return the bag size, as a percentage.
     */
    public String getFilename () {
        
        return m_filename;
    }
    
    /**
     * Sets the size of each bag, as a percentage of the training set size.
     *
     * @param newBagSizePercent the bag size, as a percentage.
     */
    public void setFilename (String newFilename) {
        
        m_filename = newFilename;
    }
}
